using System;
using System.Collections;
using System.Collections.Generic;
using SUIFW;
using UnityEngine;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.Rendering;

/*
 主题：UI管理器
    功能：是整个UI框架的核心，用户通过脚本来实现框架绝大多数的功能实现
    
    
    高内聚、低耦合
    方法单一职责
    */
public class UIManager : MonoBehaviour
{
    //字段
    private static UIManager instance;

    //UI窗体预设路径（参数1：窗体预设名称，2.标识窗体预设路径）
    private Dictionary<string, string> _DicFormsPaths;

    //预制体缓存字典
    private Dictionary<string, BaseUIForm> _DicAllUIForms;

    //已打开界面缓存字典
    private Dictionary<string, BaseUIForm> _DicCurrentShowUIForms;

    //定义栈集合，管理具备反向切换属性的窗体  存储显示当前所有反向切换的窗体类型
    private Stack<BaseUIForm> _StaCurrentUIForms;

    #region UI节点
    //UI根节点
    private Transform _TraCanvasTransfrom = null;

    //全屏显示节点
    private Transform _TraNormal = null;

    //固定显示的节点
    private Transform _TraFixed = null;

    //弹出节点
    private Transform _TraPopUp = null;

    //UI管理脚本的节点
    private Transform _TraUIScripts = null;
    #endregion

    public static UIManager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<UIManager>();
                
                if (instance == null)
                {
                    GameObject singletonObject = new GameObject(nameof(UIManager));
                    instance = singletonObject.AddComponent<UIManager>();
                }
            }
            return instance;
        }
        
        
    }

    //初始化核心数据，加载“UI窗体路径”到集合中
    private void Awake()
    {
        if (instance != null && instance != this)
        {
            Destroy(gameObject);
        }
        else
            instance = this as UIManager;
        
        DontDestroyOnLoad(gameObject);
        
        //字段初始化
        _DicFormsPaths = new Dictionary<string, string>();
        _DicAllUIForms = new Dictionary<string, BaseUIForm>();
        _DicCurrentShowUIForms = new Dictionary<string, BaseUIForm>();
        //初始化加载（根UI窗体）Canvas预设
        InitRootCanvasLoading();
        //得到UI根节点、全屏节点、固定节点、弹出节点
        _TraCanvasTransfrom = GameObject.FindGameObjectWithTag(SysDefine.SYS_TAG_CANVAS).transform;
        _TraNormal = UnityHelper.FindTheChildNode(_TraCanvasTransfrom.gameObject, SysDefine.SYS_NORMAL_NODE);
        _TraFixed = UnityHelper.FindTheChildNode(_TraCanvasTransfrom.gameObject, SysDefine.SYS_FIXED_NODE);
        _TraPopUp = UnityHelper.FindTheChildNode(_TraCanvasTransfrom.gameObject, SysDefine.SYS_POPUP_NODE);
        _TraUIScripts = UnityHelper.FindTheChildNode(_TraCanvasTransfrom.gameObject, SysDefine.SYS_SCRIPTMANAGER_NODE);


        //把本脚本作为“根UI窗体”的子节点
        this.gameObject.transform.SetParent(_TraUIScripts, false);
        //"根UI窗体"在场景转换的时候，不允许销毁
        DontDestroyOnLoad(this.gameObject);



        //初始化“UI窗体预设” 路径数据
        InitUIFormsPathData();
    }

    private void Start()
    {
        ShowUIForms("CanvasMain");
    }

    private void InitRootCanvasLoading()
    {
        Debug.Log("InitRootCanvasLoading");
        ResourcesMgr.GetInstance().LoadAsset(SysDefine.SYS_PATH_CANVAS, false);
    }



    /// <summary>
    /// 显示打开UI窗体
    /// 功能：
    /// 1.加载与判定UI窗体的名称，加载到“所有UI窗体”缓存集合中
    /// 2.根据不同的UI窗体的显示模式，分别做不同的加载处理
    /// </summary>
    /// <param name="uiFormName">UI窗体预设的名称</param>
    /// <returns></returns>
    public void ShowUIForms(string uiFormName)
    {
        BaseUIForm baseUIForm = null; //UI窗体基类
        //参数的检查
        if (string.IsNullOrEmpty(uiFormName))
        {
            return;
        }

        //指定的UI窗体的名称，加载到"所有UI窗体"缓存集合中
        if (baseUIForm != null)
        {
            return;
        }

        baseUIForm = LoadFormsToAllUIFormsCatch(uiFormName);
        if (baseUIForm == null) return;

        //是否清空栈数据
        if (baseUIForm.CurrentUIType.IsClearStack)
        {
            ClearStackArray();
        }



        //根据不同的UI窗体的显示模式，分别做不同的加载处理
        switch (baseUIForm.CurrentUIType.UIForms_ShowMode)
        {
            case UIFormShowMode.Normal: //普通显示窗口模式
                //把当前窗体加载到当前窗体集合中
                LoadUIToCurrentCache(uiFormName);
                break;
            case UIFormShowMode.ReverseChange: //反向切换窗口模式
                PushUIFormToStack(uiFormName);
                break;
            case UIFormShowMode.HideOther: //隐藏其他窗口模式
                EnterUIFormsAndHideOther(uiFormName);
                break;
            default:
                break;
        }

    }

    public void CloseUIForms(string uiFormName)
    {
        BaseUIForm baseUIForm = null; //窗体基类

        //参数检查
        if (string.IsNullOrEmpty(uiFormName))
        {
            return;
        }

        //所有UI窗体集合中，如果没有记录则直接返回
        _DicAllUIForms.TryGetValue(uiFormName, out baseUIForm);
        if (baseUIForm == null)
        {
            return;
        }

        //根据窗体不同的显示类型，分别做不同的关闭处理
        switch (baseUIForm.CurrentUIType.UIForms_ShowMode)
        {
            case UIFormShowMode.Normal:
                //普通窗体关闭方法
                ExitUIForms(uiFormName);
                break;
            case UIFormShowMode.ReverseChange:
                //反向切换窗体的关闭方法
                PopUIForms();
                break;
            case UIFormShowMode.HideOther:
                ExitUIFormsAndDisplayOther(uiFormName);
                break;
        }

    }

    #region 私有方法

    /// <summary>
    /// 根据UI窗体的名称加载到所有UI窗体缓存集合中
    /// 功能：检查所有UI窗体集合中，是否已经加载过了，否则才加载。
    /// </summary>
    /// <param name="uiFormName"></param>
    /// <returns></returns>
    private BaseUIForm LoadFormsToAllUIFormsCatch(string uiFormName)
    {
        BaseUIForm baseUIResult = null; //加载的返回UI窗体基类
        _DicAllUIForms.TryGetValue(uiFormName, out baseUIResult);
        if (baseUIResult == null)
        {
            //加载指定路径的“UI窗体”
            baseUIResult = LoadUIForms(uiFormName);
        }

        return baseUIResult;
    }

    /// <summary>
    /// 加载指定名称的UI窗体
    /// 真正的加载，位置、隐藏、加入缓存字典
    /// </summary>
    /// <param name="uiFormName"></param>
    private BaseUIForm LoadUIForms(string uiFormName)
    {
        string strUIFormPaths = null; //UI窗体路径
        GameObject goCloneUIPrefabs = null; //创建的UI克隆体预设
        BaseUIForm baseUIForm = null; //加载用的窗体基类

        //根据UI窗体名称，得到对应的加载路径
        _DicFormsPaths.TryGetValue(uiFormName, out strUIFormPaths);
        //根据UI窗体名称，加载预设克隆体
        if (!string.IsNullOrEmpty(strUIFormPaths))
        {
            goCloneUIPrefabs = ResourcesMgr.GetInstance().LoadAsset(strUIFormPaths, false);
        }

        if (_TraCanvasTransfrom != null && goCloneUIPrefabs != null)
        {
            baseUIForm = goCloneUIPrefabs.GetComponent<BaseUIForm>();
            if (baseUIForm == null)
            {
                Debug.Log("baseUIForm is null!,请先确认窗体预设对象是否挂在baseUIForm的子类脚本! 参数uiFormName = " + uiFormName);
                return null;
            }

            //位置信息
            //设置“UI克隆体”的父节点（根据）
            switch (baseUIForm.CurrentUIType.UIForms_Type)
            {
                case UIFormType.Normal: //普通窗体节点
                    goCloneUIPrefabs.transform.SetParent(_TraNormal, false);
                    break;
                case UIFormType.Fixed: //固定窗体节点
                    goCloneUIPrefabs.transform.SetParent(_TraFixed, false);
                    break;
                case UIFormType.PopUp: //弹出窗体节点
                    goCloneUIPrefabs.transform.SetParent(_TraPopUp, false);
                    break;
                default:
                    break;
            }

            //设置隐藏
            goCloneUIPrefabs.SetActive(false);
            //把克隆体加入到缓存字典中
            _DicAllUIForms.Add(uiFormName, baseUIForm);


            return baseUIForm;
        }
        else
        {
            Debug.Log("_TraCanvasTransfrom!=null && goCloneUIPrefabs!=null 条件不满足，请检查参数");
        }

        Debug.Log("不可预估的错误，请检查参数uiFormName = " + uiFormName);

        return baseUIForm;
    }

    /// <summary>
    /// 当前窗体加载到当前窗体集合中
    /// </summary>
    /// <param name="uiFormName"></param>
    private void LoadUIToCurrentCache(string uiFormName)
    {
        BaseUIForm baseUIForm; //窗体基类
        BaseUIForm baseUIFormFromAllCache; //从所有窗体集合中得到的窗体

        //如果正在显示的集合中，存在整个UI窗体，则直接返回
        _DicCurrentShowUIForms.TryGetValue(uiFormName, out baseUIForm);
        if (baseUIForm != null)
        {
            return;
        }

        //把当前窗体，加载到正在显示中
        _DicAllUIForms.TryGetValue(uiFormName, out baseUIFormFromAllCache);
        if (baseUIFormFromAllCache != null)
        {
            _DicCurrentShowUIForms.Add(uiFormName, baseUIFormFromAllCache);
            baseUIFormFromAllCache.Display(); //显示当前窗体
        }
    }

    /// <summary>
    /// UI 窗体的入栈
    /// </summary>
    /// <param name="uiFormName"></param>
    private void PushUIFormToStack(string uiFormName)
    {
        BaseUIForm baseUIForm;
        //判断栈集合中，是否有其他的窗体，有则冻结处理
        if (_StaCurrentUIForms.Count > 0)
        {
            BaseUIForm topUIForm = _StaCurrentUIForms.Peek();
            topUIForm.Freeze();
        }

        //判断UI所有窗体集合，是否有指定的UI窗体，有则处理
        _DicCurrentShowUIForms.TryGetValue(uiFormName, out baseUIForm);
        if (baseUIForm != null)
        {
            baseUIForm.Display();
            //把指定的UI窗体，入栈。
            _StaCurrentUIForms.Push(baseUIForm);
        }
        else
        {
            Debug.Log("baseUIForm == null, 请检查参数uiFormName+" + uiFormName);
        }

    }

    /// <summary>
    /// 退出指定UI窗体
    /// </summary>
    /// <param name="strUIFormName"></param>
    private void ExitUIForms(string strUIFormName)
    {
        BaseUIForm baseUIForm;
        //正在显示集合中如果没有记录则直接返回
        _DicCurrentShowUIForms.TryGetValue(strUIFormName, out baseUIForm);
        if (baseUIForm == null) return;
        //指定窗体，标记为隐藏状态，且从正在显示集合中移除
        baseUIForm.Hiding();
        _DicCurrentShowUIForms.Remove(strUIFormName);
    }

    /// <summary>
    /// 反向切换 ++窗体的出栈逻辑
    /// </summary>
    private void PopUIForms()
    {
        if (_StaCurrentUIForms.Count >= 2)
        {
            //出栈处理
            BaseUIForm topUIForms = _StaCurrentUIForms.Pop();
            //做隐藏处理
            topUIForms.Hiding();
            //出栈后，下一个窗体做“重新显示”处理
            BaseUIForm nextUIForm = _StaCurrentUIForms.Peek();
            nextUIForm.ReDisplay();
        }
        else if (_StaCurrentUIForms.Count == 1)
        {
            //出栈处理
            BaseUIForm topUIForms = _StaCurrentUIForms.Pop();
            //做隐藏处理
            topUIForms.Hiding();
        }
    }

    /// <summary>
    /// 打开窗体并隐藏其他窗体
    /// </summary>
    /// <param name="uiFormName"></param>
    private void EnterUIFormsAndHideOther(string uiFormName)
    {
        BaseUIForm baseUIForm = null; //UI窗体基类
        BaseUIForm baseUIFormFromAllCache = null; //从集合中得到的UI窗体基类
        //参数检查
        if (string.IsNullOrEmpty(uiFormName)) return;
        _DicCurrentShowUIForms.TryGetValue(uiFormName, out baseUIForm);
        if (baseUIForm != null) return;

        //把正在显示集合与栈集合中所有窗体都隐藏
        foreach (var baseUI in _DicCurrentShowUIForms)
        {
            baseUI.Value.Display();
        }

        foreach (BaseUIForm staUI in _StaCurrentUIForms)
        {
            staUI.Hiding();
        }

        //把当前窗体加入到正在显示窗体集合中，且做显示处理
        _DicAllUIForms.TryGetValue(uiFormName, out baseUIFormFromAllCache);
        if (baseUIFormFromAllCache != null)
        {
            _DicCurrentShowUIForms.Add(uiFormName, baseUIFormFromAllCache);
            //窗体显示
            baseUIFormFromAllCache.Display();
        }
    }

    /// <summary>
    ///隐藏其他属性，关闭窗体，且显示其他窗体
    /// </summary>
    /// <param name="uiFormName"></param>
    private void ExitUIFormsAndDisplayOther(string uiFormName)
    {
        BaseUIForm baseUIForms; //UI窗体基类

        //“正在显示UI窗体缓存”集合没有记录，则直接返回。
        _DicCurrentShowUIForms.TryGetValue(uiFormName, out baseUIForms);
        if (baseUIForms == null) return;

        //指定UI窗体，运行隐藏状态，且从“正在显示UI窗体缓存”集合中移除。
        baseUIForms.Hiding();
        _DicCurrentShowUIForms.Remove(uiFormName);

        //“正在显示UI窗体缓存”与“栈缓存”集合里所有窗体进行再次显示处理。
        foreach (BaseUIForm baseUIFormsItem in _DicCurrentShowUIForms.Values)
        {
            baseUIFormsItem.ReDisplay();
        }

        foreach (BaseUIForm basUIFormsItem in _StaCurrentUIForms)
        {
            basUIFormsItem.ReDisplay();
        }
    }

    /// <summary>
    /// 是否清空栈
    /// </summary>
    /// <returns></returns>
    private bool ClearStackArray()
    {
        if (_StaCurrentUIForms != null && _StaCurrentUIForms.Count >= 1)
        {
            _StaCurrentUIForms.Clear();
            return true;
        }

        return false;
    }


    /// <summary>
    /// 初始化UI窗体预设路径数据
    /// </summary>
    private void InitUIFormsPathData()
    {
        IConfigManager configMgr = new ConfigManagerByJson(SysDefine.SYS_PATH_UIFORMS_CONFIGINFO);
        if (configMgr != null)
        {
            _DicFormsPaths = configMgr.AppSetting;
        }
    }

    #endregion


    #region 测试方法

    //显示所有UI窗体数量
    public int ShowAllUIFormCount()
    {
        if (_DicAllUIForms != null)
        {
            return _DicAllUIForms.Count;
        }
        else
        {
            return 0;
        }

    }

    //显示当前窗体集合数量
    public int ShowCurrentUIFormsCount()
    {
        if (_DicCurrentShowUIForms != null)
        {
            return _DicCurrentShowUIForms.Count;
        }
        else
        {
            return 0;
        }
    }

    //显示当前栈集合数量
    public int ShowCurrentStackUIFormsCount()
    {
        if (_StaCurrentUIForms != null)
        {
            return _StaCurrentUIForms.Count;
        }
        else
        {
            return 0;
        }
    }
    #endregion
}


    
    
    
    
    
    
